package com.jiangyg.devtools.execute.code.parser;

import com.jiangyg.devtools.entity.code.BeanDefinition;
import com.jiangyg.devtools.entity.code.BeanProperty;
import com.jiangyg.devtools.toolkit.Assert;
import com.jiangyg.devtools.toolkit.CamelCaseUtils;
import org.apache.commons.lang.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.List;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 类描述：抽象的属性解析器
 *
 * @author jiangyg
 * @version 1.0
 * @date 2023年09月22日
 */
public abstract class AbstractPropertyParser implements PropertyParser {

    /**
     * 输入内容
     */
    protected final String input;

    protected final String separator = "\\t+|\\s+|(?<!number|double|float|decimal\\(\\d{1,10}),(?!\\d{1,10}\\))|，";

    public AbstractPropertyParser(String input) {
        Assert.notNull(input);
        this.input = input;
    }

    @Override
    public BeanDefinition create() throws Exception {
        final BeanDefinition definition = new BeanDefinition();

        // 属性列表
        final List<BeanProperty> props = parseBeanPropertyList();
        definition.addPropAll(props);

        // 提取字段类型和引用
        definition.extractPropTypeAndImport();

        // 设置表名
        final String tableName = parseTableName();
        if (StringUtils.isNotBlank(tableName)) {
            definition.setOriginal(tableName);
            final String camel = CamelCaseUtils.underlineToCamel(tableName);
            final String capitalize = StringUtils.capitalize(camel);
            definition.setName(capitalize);
        }

        // 设置表注释
        final String comment = parseTableComment();
        if (StringUtils.isNotBlank(comment)) {
            definition.setComment(comment);
        }

        return definition;
    }

    /**
     * 功能描述：解析属性列表
     *
     * @return 属性列表
     */
    protected abstract List<BeanProperty> parseBeanPropertyList() throws Exception;

    /**
     * 功能描述：获取表名称
     *
     * @return 表名称
     */
    protected String parseTableName() {
        return StringUtils.EMPTY;
    }

    /**
     * 功能描述：获取表注释
     *
     * @return 表注释
     */
    protected String parseTableComment() {
        return StringUtils.EMPTY;
    }

    /**
     * 功能描述：构建 Bean 属性
     *
     * @param name    属性名
     * @param type    属性类型
     * @param comment 属性注释
     * @return 属性
     */
    protected BeanProperty buildBeanProperty(String name, String type, String comment) {
        final BeanProperty prop = new BeanProperty();
        prop.setRawName(name);
        prop.setName(CamelCaseUtils.underlineToCamel(name));
        prop.setRawType(decidePropertyType(type));
        prop.setComment(comment);
        prop.setSetter(setterMethodName(prop));
        prop.setGetter(getterMethodName(prop));
        return prop;
    }

    /**
     * 功能描述：尝试通过正则获取字符串内的值
     *
     * @param regexps   正则数组
     * @param string    字符串
     * @param groupName 分组名
     * @return 值
     */
    protected String attemptObtainValueByRegex(String[] regexps, String string, String groupName) {
        for (String regex : regexps) {
            final Pattern pattern = Pattern.compile(regex);
            final Matcher matcher = pattern.matcher(string);
            if (matcher.find()) {
                final String tzn = matcher.group(groupName);
                if (StringUtils.isNotBlank(tzn)) {
                    return tzn;
                }
            }
        }
        return StringUtils.EMPTY;
    }

    /**
     * 功能描述：按行读取字符串内容
     *
     * @param content  字符串内容
     * @param consumer 行处理
     * @throws IOException 异常
     */
    protected void readByLine(String content, Consumer<String> consumer) throws IOException {
        String line;
        try (StringReader reader = new StringReader(content); BufferedReader buffer = new BufferedReader(reader)) {
            while ((line = buffer.readLine()) != null) {
                if (StringUtils.isBlank(line)) {
                    continue;
                }
                if (consumer != null) {
                    consumer.accept(line);
                }
            }
        }
    }

    /**
     * 功能描述：根据属性生成 get 方法名
     *
     * @param prop 属性
     * @return 方法名
     */
    protected String getterMethodName(BeanProperty prop) {
        final String methodName = StringUtils.capitalize(prop.getName());
        if (StringUtils.equalsIgnoreCase(prop.getType(), Boolean.class.getSimpleName())) {
            return "is" + methodName;
        }
        return "get" + methodName;
    }

    /**
     * 功能描述：根据属性生成 set 方法名
     *
     * @param prop 属性
     * @return 方法名
     */
    protected String setterMethodName(BeanProperty prop) {
        final String methodName = StringUtils.capitalize(prop.getName());
        return "set" + methodName;
    }

    /**
     * 功能描述：判断属性类型
     *
     * @param type 类型字符串
     * @return 属性类型
     */
    protected String decidePropertyType(String type) {
        if (StringUtils.equalsIgnoreCase(type, "char(1)")) {
            return java.lang.Character.class.getName();
        }
        if (Pattern.matches("(?i)number(\\d+,0)", type)) {
            return java.lang.Integer.class.getName();
        }
        if (Pattern.matches("(?i)number(\\d+,\\d+)", type)) {
            return java.math.BigDecimal.class.getName();
        }
        if (StringUtils.equalsIgnoreCase(type, "DATE")) {
            return java.util.Date.class.getName();
        }
        if (StringUtils.equalsIgnoreCase(type, "CLOB")) {
            return java.sql.Clob.class.getName();
        }
        if (StringUtils.equalsIgnoreCase(type, "Blob")) {
            return java.sql.Blob.class.getName();
        }
        return java.lang.String.class.getName();
    }

}
